﻿using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WPRD.Models
{
    /// <summary>
    /// 数据文件模型
    /// </summary>
    public class DataFile : ObservableObject
    {
        #region Private Properties
        /// <summary>
        /// 数据文件路径
        /// </summary>
        private string _path;

        /// <summary>
        /// 文件名
        /// </summary>
        private DataFileName _dataFileName;

        /// <summary>
        /// 区站号
        /// </summary>
        private string _stationNumber;

        /// <summary>
        /// 天线所在经度
        /// </summary>
        private Decimal _longitude;

        /// <summary>
        /// 天线所在纬度
        /// </summary>
        private Decimal _latitude;

        /// <summary>
        /// 海拔高度
        /// </summary>
        private Decimal _altitude;

        /// <summary>
        /// 雷达型号
        /// </summary>
        private string _radarType;

        /// <summary>
        /// 观测时间
        /// </summary>
        private DateTime _observationTime;

        /// <summary>
        /// 产品标识（ROBS：实时，HOBS：半小时，OOBS：一小时）
        /// </summary>
        private string _product;

        /// <summary>
        /// 质量控制列表
        /// </summary>
        private List<QualityControl> _qualityControlList;

        /// <summary>
        /// 质量代码
        /// </summary>
        private int _qualityCode;

        /// <summary>
        /// 质量信息
        /// </summary>
        private string _qualityInfo;
        #endregion

        #region Creator
        /// <summary>
        /// 构造函数
        /// </summary>
        public DataFile()
        {
            _qualityControlList = new List<QualityControl>();
        }

        #endregion

        #region Public Properties
        /// <summary>
        /// 数据文件路径
        /// </summary>
        public string Path
        {
            get
            {
                return _path;
            }
            set
            {
                if (value == _path)
                    return;
                _path = value;
                RaisePropertyChanged("Path");
            }
        }

        /// <summary>
        /// 文件名
        /// </summary>
        public DataFileName DataFileName
        {
            get
            {
                return _dataFileName;
            }
            set
            {
                if (value == _dataFileName)
                    return;
                _dataFileName = value;
                RaisePropertyChanged("DataFileName");
            }
        }

        /// <summary>
        /// 区站号
        /// </summary>
        public string StationNumber
        {
            get
            {
                return _stationNumber;
            }
            set
            {
                if (value == _stationNumber)
                    return;
                _stationNumber = value;
                RaisePropertyChanged("StationNumber");
            }
        }

        /// <summary>
        /// 天线所在经度
        /// </summary>
        public Decimal Longitude
        {
            get
            {
                return _longitude;
            }
            set
            {
                if (value == _longitude)
                    return;
                _longitude = value;
                RaisePropertyChanged("Longitude");
            }
        }

        /// <summary>
        /// 天线所在纬度
        /// </summary>
        public Decimal Latitude
        {
            get
            {
                return _latitude;
            }
            set
            {
                if (value == _latitude)
                    return;
                _latitude = value;
                RaisePropertyChanged("Latitude");
            }
        }

        /// <summary>
        /// 海拔高度
        /// </summary>
        public Decimal Altitude
        {
            get
            {
                return _altitude;
            }
            set
            {
                if (value == _altitude)
                    return;
                _altitude = value;
                RaisePropertyChanged("Altitude");
            }
        }

        /// <summary>
        /// 雷达型号
        /// </summary>
        public string RadarType
        {
            get
            {
                return _radarType;
            }
            set
            {
                if (value == _radarType)
                    return;
                _radarType = value;
                RaisePropertyChanged("RadarType");
            }
        }

        /// <summary>
        /// 观测时间
        /// </summary>
        public DateTime ObservationTime
        {
            get
            {
                return _observationTime;
            }
            set
            {
                if (value == _observationTime)
                    return;
                _observationTime = value;
                RaisePropertyChanged("ObservationTime");
            }
        }

        /// <summary>
        /// 产品标识（ROBS：实时，HOBS：半小时，OOBS：一小时）
        /// </summary>
        public string Product
        {
            get
            {
                return _product;
            }
            set
            {
                if (value == _product)
                    return;
                _product = value;
                RaisePropertyChanged("Product");
            }
        }

        /// <summary>
        /// 质量控制列表
        /// </summary>
        public List<QualityControl> QualityControlList
        {
            get
            {
                return _qualityControlList;
            }
            set
            {
                if (value == _qualityControlList)
                    return;
                _qualityControlList = value;
                RaisePropertyChanged("QualityControlList");
            }
        }

        /// <summary>
        /// 质量代码
        /// </summary>
        public int QualityCode
        {
            get
            {
                return _qualityCode;
            }
            set
            {
                if (value == _qualityCode)
                    return;
                _qualityCode = value;
                RaisePropertyChanged("QualityCode");
            }
        }

        /// <summary>
        /// 质量信息
        /// </summary>
        public string QualityInfo
        {
            get
            {
                return _qualityInfo;
            }
            set
            {
                if (value == _qualityInfo)
                    return;
                _qualityInfo = value;
                RaisePropertyChanged("QualityInfo");
            }
        }
        #endregion
    }

    public static class DataFileExtension
    {
        /// <summary>
        /// 转换时间
        /// </summary>
        /// <param name="dateTimeString">时间字符串</param>
        /// <returns></returns>
        private static DateTime ParseDateTime(string dateTimeString)
        {
            if (dateTimeString.Length != 14)
                throw new Exception("时间字符串长度应为14");
            string formatDateTimeString = String.Format("{0}/{1}/{2} {3}:{4}:{5}",
                    dateTimeString.Substring(0, 4),
                    dateTimeString.Substring(4, 2),
                    dateTimeString.Substring(6, 2),
                    dateTimeString.Substring(8, 2),
                    dateTimeString.Substring(10, 2),
                    dateTimeString.Substring(12, 2));
            return Convert.ToDateTime(formatDateTimeString);
        }

        /// <summary>
        /// 解析数据文件内容
        /// </summary>
        /// <param name="dataFile"></param>
        public static void AnalysisDataFile(this DataFile dataFile)
        {
            try
            {
                //解析文件内容
                using (StreamReader streamReader = new StreamReader(dataFile.Path, Encoding.Default))
                {
                    int lineNumber = 0;
                    string line;
                    while ((line = streamReader.ReadLine()) != null)
                    {
                        if (lineNumber == 0)
                        {
                            //Do Nothing
                        }
                        else if (lineNumber == 1)
                        {
                            string[] properties = line.Split(' ');
                            if (properties.Length != 6)
                                throw new Exception("数据文件第二行格式错误");
                            string stationNumber = properties[0];
                            Decimal longitude;
                            try
                            {
                                longitude = Convert.ToDecimal(properties[1]);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("经度格式错误", ex);
                            }
                            Decimal latitude;
                            try
                            {
                                latitude = Convert.ToDecimal(properties[2]);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("纬度格式错误", ex);
                            }
                            Decimal altitude;
                            try
                            {
                                altitude = Convert.ToDecimal(properties[3]);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("高度格式错误", ex);
                            }
                            string radarType = properties[4];
                            string observationTimeString = properties[5];
                            DateTime observationTime;
                            try
                            {
                                observationTime = ParseDateTime(observationTimeString);
                            }
                            catch (Exception ex)
                            {
                                throw new Exception("观测时间格式错误", ex);
                            }
                            dataFile.StationNumber = stationNumber;
                            dataFile.Longitude = longitude;
                            dataFile.Latitude = latitude;
                            dataFile.Altitude = altitude;
                            dataFile.RadarType = radarType;
                            dataFile.ObservationTime = observationTime;
                        }
                        else if (lineNumber == 2)
                        {
                            dataFile.Product = line;
                        }
                        else
                        {
                            if (line == "NNNN")
                                break;
                            QualityControl qualityControl = new QualityControl
                            {
                                DataLine = line,
                                StationNumber = dataFile.DataFileName.StationNumber,
                                Product = dataFile.DataFileName.Product
                            };
                            //解析数据行
                            qualityControl.AnalysisQualityControl();
                            //添加数据文件
                            dataFile.QualityControlList.Add(qualityControl);
                        }
                        lineNumber++;
                    }
                }
            }
            catch (Exception ex)
            {
                dataFile.QualityCode = 2;
                dataFile.QualityInfo = String.Format("数据文件格式错误\n{0}", ex.Message);
            }
        }

        /// <summary>
        /// 解析数据文件名
        /// </summary>
        /// <param name="dataFile">数据文件</param>
        public static void AnalysisDataFileName(this DataFile dataFile)
        {
            try
            {
                string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(dataFile.Path);
                string[] dataFileProperties = fileNameWithoutExtension.Split('_');
                if (dataFileProperties.Length != 9)
                    throw new Exception("数据文件名应为字符‘_’分隔的9段");
                string stationNumber = dataFileProperties[3];
                string observationTimeString = dataFileProperties[4];
                DateTime observationTime;
                try
                {
                    observationTime = ParseDateTime(observationTimeString);
                }
                catch (Exception ex)
                {
                    throw new Exception("观测时间格式错误", ex);
                }
                string radarType = dataFileProperties[7];
                string product = dataFileProperties[8];
                dataFile.DataFileName = new DataFileName
                {
                    StationNumber = stationNumber,
                    ObservationTime = observationTime,
                    RadarType = radarType,
                    Product = product
                };
            }
            catch (Exception ex)
            {
                throw new Exception("数据文件名格式错误", ex);
            }
        }

        /// <summary>
        /// 内部一致性检查
        /// </summary>
        /// <param name="dataFile">数据文件</param>
        public static void ConsistencyCheck(this DataFile dataFile)
        {
            if (dataFile.DataFileName.StationNumber != dataFile.StationNumber ||
                dataFile.DataFileName.ObservationTime != dataFile.ObservationTime ||
                dataFile.DataFileName.RadarType != dataFile.RadarType ||
                dataFile.DataFileName.Product != dataFile.Product)
            {
                dataFile.QualityCode = 2;
                dataFile.QualityInfo = "未通过内部一致性检查";
            }
        }

        /// <summary>
        /// 值域范围检查
        /// </summary>
        /// <param name="dataFile">数据文件</param>
        /// <param name="radarSite">雷达台站</param>
        public static void RangeCheck(this DataFile dataFile, RadarSite radarSite)
        {
            if (dataFile.Longitude < (radarSite.Longitude - 1) ||
                dataFile.Longitude > (radarSite.Longitude + 1) ||
                dataFile.Latitude < (radarSite.Latitude - 1) ||
                dataFile.Latitude > (radarSite.Latitude + 1) ||
                dataFile.Altitude < (radarSite.Altitude - 50) ||
                dataFile.Altitude > (radarSite.Altitude + 500))
            {
                dataFile.QualityCode = 2;
                dataFile.QualityInfo = "未通过值域范围检查";
            }
        }

        public static void DataLineCheck(this DataFile dataFile)
        {
            dataFile.QualityControlList.ForEach(qc =>
            {
                if (dataFile.QualityCode == 2)
                {
                    qc.QualityCode = dataFile.QualityCode;
                    qc.QualityInfo = dataFile.QualityInfo;
                }
                else
                {
                    if (qc.QualityCode < 2)
                    {
                        if (qc.HorizontalWindDirection < 0 || qc.HorizontalWindDirection > 360)
                        {
                            qc.QualityCode = 2;
                            qc.QualityInfo = "水平风向超出值域范围";
                        }
                        else if ((qc.Altitude <= 1000 && qc.HorizontalWindVelocity > 70) ||
                           (qc.Altitude <= 2500 && qc.HorizontalWindVelocity > 90) ||
                           (qc.Altitude <= 4000 && qc.HorizontalWindVelocity > 120) ||
                           (qc.HorizontalWindVelocity > 200))
                        {
                            qc.QualityCode = 2;
                            qc.QualityInfo = "水平风速超出极值";
                        }
                        else if (qc.VerticalWindVelocity > 4)
                        {
                            qc.QualityCode = 2;
                            qc.QualityInfo = "垂直风速超出极值";
                        }
                        else if (qc.HorizontalCredibility != 100 || qc.VerticalCredibility != 100)
                        {
                            qc.QualityCode = 2;
                            qc.QualityInfo = "可信度为错误";
                        }
                    }
                }
            });
        }

    }
}
